﻿using System;
using System.Linq;
using Quartz;
using ZilLion.Core.ConfigManager.Manager;
using ZilLion.TaskManager.Core.Infrastructure;
using ZilLion.TaskManager.Entity.Config;
using ZilLion.TaskManager.Entity.Entity;
using ZilLion.TaskManager.Repository;

namespace ZilLion.TaskManager.Core.Quartz
{
    /// <summary>
    ///     自定义触发器监听
    /// </summary>
    public class AppDomainCustomTriggerListener : ITriggerListener
    {
        private readonly TaskStateRespository _taskStateRespository;

        public AppDomainCustomTriggerListener(TaskConfig config)
        {
            _taskStateRespository = new TaskStateRespository();
            Name = config.TaskModule;
        }


        public string Name { get; }

        /// <summary>
        ///     Trigger被激发 它关联的job即将被运行
        /// </summary>
        /// <param name="trigger">触发器</param>
        /// <param name="context">上下文</param>
        public void TriggerFired(ITrigger trigger, IJobExecutionContext context)
        {
            CustomTaskLogger.Print(Loglevel.Trace,
                $"{context.JobDetail.JobType.Name}在{DateTime.Now:yyyy-MM-dd HH:mm:ss}即将触发!");
        }

        /// <summary>
        ///     Trigger被激发 它关联的job即将被运行,先执行(1)，在执行(2) 如果返回TRUE 那么任务job会被终止
        /// </summary>
        /// <param name="trigger"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        bool ITriggerListener.VetoJobExecution(ITrigger trigger, IJobExecutionContext context)
        {
            var response = _taskStateRespository.GetTaskStateById(context.JobDetail.Key.Name);
            var taskStateEntity = response?.TaskStates.FirstOrDefault();
            if (taskStateEntity != null && taskStateEntity.Taskstatus == 0)
                return false;
            return true;
        }

        /// <summary>
        ///     错过触发时调用
        /// </summary>
        /// <param name="trigger">触发器</param>
        void ITriggerListener.TriggerMisfired(ITrigger trigger)
        {
            CustomTaskLogger.Print(Loglevel.Warn, $"{trigger.JobKey.Name}在{DateTime.Now:yyyy-MM-dd HH:mm:ss}错过触发！");
        }

        /// <summary>
        ///     Job完成时调用
        /// </summary>
        /// <param name="trigger">触发器</param>
        /// <param name="context">上下文</param>
        /// <param name="triggerInstructionCode"></param>
        void ITriggerListener.TriggerComplete(ITrigger trigger, IJobExecutionContext context,
            SchedulerInstruction triggerInstructionCode)
        {
            if (triggerInstructionCode != SchedulerInstruction.NoInstruction)
            {
                #region Customexcption Handler

                CustomTaskLogger.Print(Loglevel.Trace,
                    $"{context.JobDetail.JobType.Name}在{DateTime.Now:yyyy-MM-dd HH:mm:ss}执行失败!");
                var taskStateRespository = new TaskStateRespository();
                taskStateRespository.ReportTaskError(
                    context.JobDetail.Key.Name,
                    ZilLionConfigurationManager.GetConfigInstance<TaskManagerCommonConfig>().ClientNo);

                #endregion
            }
            else
            {
                if (context.NextFireTimeUtc == null) return;
                var nextRunTime = TimeZoneInfo.ConvertTimeFromUtc(context.NextFireTimeUtc.Value.DateTime,
                    TimeZoneInfo.Local);
                var taskid = trigger.JobKey.Name;
                CustomTaskLogger.Print(Loglevel.Trace,
                    $"{context.JobDetail.JobType.Name}在{DateTime.Now:yyyy-MM-dd HH:mm:ss}触发成功!");

                #region 更新状态表

                var nodeid = ZilLionConfigurationManager.GetConfigInstance<TaskManagerCommonConfig>().ClientNo;
                var runlogresponse = _taskStateRespository.GetTaskStateById(taskid, nodeid);
                if (runlogresponse != null && runlogresponse.TaskStates != null)
                {
                    var first = runlogresponse.TaskStates.FirstOrDefault();
                    {
                        if (first != null)
                        {
                            first.Tasknextruntime = nextRunTime;
                            first.Tasklastruntime = DateTime.Now;
                            _taskStateRespository.ReportTaskExcuted(first);
                        }
                    }
                }

                #endregion
            }
        }
    }
}